/*
 * DrawPage.h
 *
 *  Created on: 2010-10-25
 *      Author: wenjian
 */

#ifndef DRAWPAGE_H_
#define DRAWPAGE_H_
#include "../commons.h"
#include "../draw/AbstractDrawPage.h"
#include <wingdi.h>
#include <GdiPlus.h>
#include "Element.h"
#include "Elements.h"
#include "Selection.h"
#include "Layer.h"
#include "ImageLayerMerger.h"

namespace Ed {
  class DrawPage: public AbstractDrawPage {
    public:
      DrawPage(HWND hWnd, real x=0.0, real y=0.0, real width=0.0, real heigth=0.0);
      virtual ~DrawPage();


      /**
       * 设置画布位置，(x,y)为坐标，(w, h)为宽度和高度
       */
      virtual inline void setGeometry(real x, real y, real w, real h){
        geometry.X = x;
        geometry.Y = y;
        geometry.Width = w;
        geometry.Height = h;
      }

      /**
       * 设置画布位置(x,y)坐标，宽度，高度
       */
      virtual inline void setGeometry(const Gdiplus::RectF& rect){
        geometry = rect;
      }

      /**
       * 返回画布位置(x,y)坐标，宽度，高度
       */
      virtual inline const Gdiplus::RectF& getGeometry() const{
        return geometry;
      }

      /**
       * 设置可视区域, x,y坐标系为画布坐标系
       */
      virtual inline void setVisibleRegion(real x, real y, real w, real h){
        visibleRegion.X = x;
        visibleRegion.Y = y;
        visibleRegion.Width = w;
        visibleRegion.Height = h;
      }

      /**
       * 设置可视区域, x,y坐标系为画布坐标系
       */
      virtual inline void setVisibleRegion(const Gdiplus::RectF& rect){
        visibleRegion = rect;
      }

      /**
       * 返回可视区域
       */
      virtual inline const Gdiplus::RectF& getVisibleRegion() const{
        return visibleRegion;
      }


      /**
       * 返回x坐标
       */
      virtual inline real x() const{
        return geometry.X;
      }
      /**
       * 返回y坐标
       */
      virtual inline real y() const{
        return geometry.Y;
      }

      /**
       * 返回宽度
       */
      virtual inline real width() const{
        return geometry.Width;
      }
      /**
       * 返回高度
       */
      virtual inline real height() const{
        return geometry.Height;
      }

      /**
       * 画所有图层, 将从最低层图层开始绘制
       */
      virtual void draw(Gdiplus::Graphics* g);

      /**
       * 刷新缓冲区, flag为true，才会调用draw()方法绘图
       */
      virtual void refresh(bool flag = false);

      /**
       * 跟踪鼠标事件
       */
      virtual void trackMouseEvent(EventType type, int x, int y, unsigned int buttons, void* source=NULL);

      /**
       * 跟踪鼠标事件
       */
      virtual void trackMouseEvent(EventType type, int x, int y, unsigned int buttons, const KeySequence& ks,  void* source=NULL);

      /**
       * 处理系统光标事件, 刷新鼠标光标
       */
      virtual bool refreshCursor();

      HDC getPageHDC(){
        return bufferDC;
      }

      Gdiplus::Graphics* getPageGraphics(){
        return graphics;
      }

      void setLayerMerger(LayerMerger* lm);

      LayerMerger* getLayerMerger(){
        if(!layerMerger){
          layerMerger = &imageLayerMerger;
        }
        return layerMerger;
      }

    protected:
      HDC hostDC;
      HDC bufferDC;
      Gdiplus::Graphics* graphics;
      //画布位置
      Gdiplus::RectF geometry;
      //可视矩形区
      Gdiplus::RectF visibleRegion;

      /**
       * 初始化
       */
      virtual void init(HWND hWnd);


    private:
      ImageLayerMerger imageLayerMerger;
      LayerMerger* layerMerger;

    private:
      static ULONG_PTR gpToken;
    public:
      /**
       * 准备Gdiplus, 在调用GdiplusDrawPage.init(HWND hWnd)方法之前调用此静态方法
       */
      static void startupGdiplus(){
        Gdiplus::GdiplusStartupInput gsi;
        Gdiplus::GdiplusStartup(&gpToken, &gsi, NULL );
      }

      /**
       * 关闭Gdiplus, 在delete GdiplusDrawPage后调用此静态方法
       */
      static void shutdownGdiplus(){
        Gdiplus::GdiplusShutdown(gpToken);
      }
  };
}
#endif /* DRAWPAGE_H_ */
